package com.flyan.danmuhunter.bilibili.data;

import lombok.Getter;

import java.nio.ByteBuffer;

/**
 * 网络封包头
 *
 *
 *
 * 头部格式：
 * 偏移量	长度	    含义
 * 0	    4	    封包总大小
 * 4	    2	    头部长度
 * 6	    2	    协议版本
 * 8	    4	    操作码（封包类型）
 * 12	    4	    sequence，可以取常数1
 *
 * 已知的操作码：
 * 操作码	含义
 * 2	    客户端发送的心跳包
 * 7	    客户端发送认证并加入房间
 * 3	    人气值，数据不是JSON，是4字节整数
 * 5	    命令，数据中[‘cmd’]表示具体命令
 * 8	    服务器发送的心跳包(没见过)
 *
 * @author flyan
 * @version 1.0
 * @date 2022/6/7
 */
@Getter
public class Header {

    public static final int HEADER_SIZE = 16;

    /**
     * 头据
     */
    private final ByteBuffer byteBuffer;

    /**
     * 封包总大小
     */
    private final int packageTotalSize;

    /**
     * 头部长度
     */
    private final int headerLength;

    /**
     * 协议版本
     *
     * 当协议版本为 0 时，数据无压缩，
     * 而协议版本为 2 时，数据是有进行压缩的
     */
    private final int protocolVersion;

    /**
     * 操作码（封包类型）
     */
    private final Op op;

    /**
     * 序列号
     */
    private int sequence;

    public Header(ByteBuffer bytes) {
        this.byteBuffer = bytes;
        this.packageTotalSize = bytes.getInt();
        this.headerLength = bytes.getShort();
        this.protocolVersion = bytes.getShort();
        this.op = new Op(bytes.getInt());
        this.sequence = bytes.getInt();
    }

    public Header(int packageTotalSize, int headerLength, int protocolVersion, int opVal, int sequence) {
        this.packageTotalSize = packageTotalSize;
        this.headerLength = headerLength;
        this.protocolVersion = protocolVersion;
        this.op = new Op(opVal);
        this.sequence = sequence;

        this.byteBuffer = ByteBuffer.allocate(HEADER_SIZE);
        this.byteBuffer.putInt(0, packageTotalSize);
        this.byteBuffer.putShort(4, (short) headerLength);
        this.byteBuffer.putShort(6, (short) protocolVersion);
        this.byteBuffer.putInt(8, opVal);
        this.byteBuffer.putInt(12, sequence);
    }

    @Override
    public String toString() {
        return "Header{" +
                "packageTotalSize=" + packageTotalSize +
                ", headerLength=" + headerLength +
                ", protocolVersion=" + protocolVersion +
                ", op=" + op +
                ", sequence=" + sequence +
                '}';
    }
}
